<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        canvas {
            border: 1px solid #000;
            float: left; /* 使得画布浮动在左边 */
        }

        #score #level {
            float: left; /* 使得分数显示在画布右侧 */
            margin-left: 20px; /* 调整分数和画布之间的间距 */
            font-size: 18px;
        }
        #nextPieceCanvas {
            border: 1px solid #000;
            float: left; /* 使得预览画布浮动在右边 */
            margin-left: 20px; /* 调整预览画布和分数之间的间距 */
        }
    </style>
    <title>Tetris Game</title>
</head>
<body>
    <canvas id="tetrisCanvas" width="300" height="600"></canvas>
    <div id="score">Score: 0</div>
    <div id="level">Level: 1</div>
    <canvas id="nextPieceCanvas" width="120" height="100"></canvas>
    <script>
        // 游戏场地大小
        const ROWS = 20;
        const COLS = 10;
        const CELL_SIZE = 30;
        var level=1;

        const canvas = document.getElementById("tetrisCanvas");
        const context = canvas.getContext("2d");

        // 创建游戏场地的二维数组，初始值为0（0代表空格）
        function createPlayfield() {
            const playfield = [];
            for (let y = 0; y < ROWS; y++) {
                playfield[y] = [];
                for (let x = 0; x < COLS; x++) {
                    playfield[y][x] = 0;
                }
            }
            return playfield;
        }

        // 画布上绘制方块
        function drawBlock(x, y, color, context) {
            context.fillStyle = color;
            context.fillRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
            context.strokeStyle = "#000";
            context.strokeRect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE);
        }

        // 在画布上绘制整个游戏场地
        function drawPlayfield(playfield) {
            for (let y = 0; y < ROWS; y++) {
                for (let x = 0; x < COLS; x++) {
                    if (playfield[y][x] !== 0) {
                        drawBlock(x, y, "cyan",context); // 假设方块颜色为青色
                    }
                }
            }
        }

        // 渲染玩家的当前方块
        function drawPlayerTetromino(player) {
            for (let y = 0; y < player.tetromino.length; y++) {
                for (let x = 0; x < player.tetromino[y].length; x++) {
                    if (player.tetromino[y][x] !== 0) {
                        drawBlock(player.pos.x + x, player.pos.y + y, "orange",context); // 假设玩家方块颜色为橙色
                    }
                }
            }
        }

        // 渲染游戏
        function renderGame() {
            context.clearRect(0, 0, canvas.width, canvas.height);

            drawPlayfield(playfield);
            drawPlayerTetromino(player);
        }

        // 检测方块是否与其他方块或游戏场地的边缘碰撞
        function collision(playfield, playerPos, tetromino) {
            for (let y = 0; y < tetromino.length; y++) {
                for (let x = 0; x < tetromino[y].length; x++) {
                    if (
                        tetromino[y][x] !== 0 &&
                        (playfield[y + playerPos.y] && playfield[y + playerPos.y][x + playerPos.x]) !== 0
                    ) {
                        return true;
                    }
                }
            }
            return false;
        }

        // 清除满行
        function clearRows() {
            let ys=[];
            for (let y = ROWS - 1; y >= 0; y--) {
                if (playfield[y].every(cell => cell !== 0)) {
                    ys.push(y);
                    player.score += 100;
                    // playfield.splice(y, 1); // 移除满行
                    // playfield.unshift(Array(COLS).fill(0)); // 在顶部插入新的空行
                    // player.score += 100; // 假设每清除一行得100分
                    // y++; // 修复BUG：继续检查当前行，因为新插入的行可能也是满行
                }
            }
            setTimeout(()=>{
                for (let i = 0; i < ys.length; i++) {
                    playfield.splice(ys[i], 1);
                    playfield.unshift(Array(COLS).fill(0));
                }
            },100)
            updateScore();
        }
        // 更新分数显示
        function updateScore() {
            const scoreElement = document.getElementById('score');
            scoreElement.textContent = 'Score: ' + player.score;
            level= Math.floor(player.score/500)+1;
            const levelElement = document.getElementById('level');
            levelElement.textContent = 'Score: ' + level;
        }
        let isPlay=true;
        // 方块下落
        function moveDown() {
            if(isPlay){
                player.pos.y++;
                if (collision(playfield, player.pos, player.tetromino)) {
                    // 如果下落后发生碰撞，将方块固定在场地中，然后生成新的方块
                    player.pos.y--;
                    mergePlayerTetromino();
                    clearRows(); // 检查并清除满行
                    initGame();
                    if(nextTetr&&isGameOver(nextTetr)){
                        isPlay=false;
                        alert("游戏结束");
                        window.location.reload();
                    }
                }
            }
        }

        // 向左移动方块
        function moveLeft() {
            player.pos.x--;
            if (collision(playfield, player.pos, player.tetromino)) {
                // 如果向左移动后发生碰撞，恢复到移动前的位置
                player.pos.x++;
            }
        }

        // 向右移动方块
        function moveRight() {
            player.pos.x++;
            if (collision(playfield, player.pos, player.tetromino)) {
                // 如果向右移动后发生碰撞，恢复到移动前的位置
                player.pos.x--;
            }
        }

        // 旋转玩家方块
        function rotatePlayerTetromino() {
            const clonedTetromino = JSON.parse(JSON.stringify(player.tetromino));
            const rotatedTetromino = rotate(clonedTetromino);

            if (!collision(playfield, player.pos, rotatedTetromino)) {
                player.tetromino = rotatedTetromino;
            }
        }

        // 随机生成新的方块
        function createTetromino() {
            const tetrominos = 'IJLOSTZ';
            const randTetromino =
                TETROMINOS[tetrominos[Math.floor(Math.random() * tetrominos.length)]];
            return randTetromino;
        }

        // 将玩家方块合并到场地中
        function mergePlayerTetromino() {
            for (let y = 0; y < player.tetromino.length; y++) {
                for (let x = 0; x < player.tetromino[y].length; x++) {
                    if (player.tetromino[y][x] !== 0) {
                        playfield[y + player.pos.y][x + player.pos.x] = 1;
                    }
                }
            }
        }

        // 旋转方块
        function rotate(tetromino) {
            const N = tetromino.length;
            for (let y = 0; y < N / 2; y++) {
                for (let x = y; x < N - y - 1; x++) {
                    const temp = tetromino[y][x];
                    tetromino[y][x] = tetromino[N - 1 - x][y];
                    tetromino[N - 1 - x][y] = tetromino[N - 1 - y][N - 1 - x];
                    tetromino[N - 1 - y][N - 1 - x] = tetromino[x][N - 1 - y];
                    tetromino[x][N - 1 - y] = temp;
                }
            }
            return tetromino;
        }

        // 玩家当前方块和位置
        const player = {
            pos: { x: 0, y: 0 },
            tetromino: null,
            score: 0
        };

        // 定义各种形状的方块模板
        const TETROMINOS = {
            'I': [
                [0, 0, 0, 0],
                [1, 1, 1, 1],
                [0, 0, 0, 0],
                [0, 0, 0, 0]
            ],
            'J': [
                [1, 0, 0],
                [1, 1, 1],
                [0, 0, 0]
            ],
            'L': [
                [0, 0, 1],
                [1, 1, 1],
                [0, 0, 0]
            ],
            'O': [
                [1, 1],
                [1, 1]
            ],
            'S': [
                [0, 1, 1],
                [1, 1, 0],
                [0, 0, 0]
            ],
            'T': [
                [0, 1, 0],
                [1, 1, 1],
                [0, 0, 0]
            ],
            'Z': [
                [1, 1, 0],
                [0, 1, 1],
                [0, 0, 0]
            ]
        };
        // 判断游戏是否结束(获取下一个方块nextTetromino)
        function isGameOver(nextTetromino) {
            // 检查是否可以在初始位置放置下一个方块
            for (let y = 0; y < nextTetromino.length; y++) {
                for (let x = 0; x < nextTetromino[y].length; x++) {
                    if (
                        nextTetromino[y][x] !== 0 &&
                        (playfield[y] && playfield[y][x + Math.floor(COLS / 2)] !== 0)
                    ) {
                        return true; // 游戏结束
                    }
                }
            }

            return false; // 游戏未结束
        }
		// 游戏场地
        const playfield = createPlayfield();

        // 在画布上绘制预览方块
        function drawNextPiece(nextTetromino) {
            const nextPieceCanvas = document.getElementById("nextPieceCanvas");
            const nextPieceContext = nextPieceCanvas.getContext("2d");

            nextPieceContext.clearRect(0, 0, nextPieceCanvas.width, nextPieceCanvas.height);

            for (let y = 0; y < nextTetromino.length; y++) {
                for (let x = 0; x < nextTetromino[y].length; x++) {
                    if (nextTetromino[y][x] !== 0) {
                        drawBlock(x, y, "gray", nextPieceContext);
                    }
                }
            }
        }

        // 更新预览方块
        function updateNextPiece() {
            const nextTetromino = createTetromino();
            drawNextPiece(nextTetromino);
            return nextTetromino;
        }
        let nextTetr=null;
        // 初始化游戏
        function initGame() {
            player.pos = { x: COLS / 2 - 1, y: 0 };
            player.tetromino = nextTetr||createTetromino();
            if(player.tetromino==TETROMINOS['I']){
                player.pos.y=-1;
            }
            nextTetr=updateNextPiece(); // 初始化时更新预览方块
        }

        initGame();
        // 处理键盘事件
        window.addEventListener('keydown', (e) => {
            switch (e.keyCode) {
                case 37:
                case 65:
                    moveLeft();
                    break;
                case 38:
                case 87:   
                    rotatePlayerTetromino();
                    break;
                case 39:
                case 68:
                    moveRight();
                    break;
                case 40:
                case 83:
                    moveDown();
                    break;
            }
            renderGame();
        });
        function update(){
            renderGame();
            moveDown();
        }
        update();
        var time=0
        // 启动游戏循环
        setInterval(() => {
            time++;
            if(time>=(60-level)){
                update();
                time=0;
            }
        }, 16.6666); // 每秒执行一次游戏循环
    </script>
</body>
</html>
